/*
 *      dilca-gateway.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */
#define _VERSION "dilca - Gateway (v0.0.1)"
#define _VERSION1 "0.0.1"



#include <libidxp.h>
#include "lightlog.c"


#define DILCA_MAX_HOSTS 100
#ifdef _WIN32
#define MOVECMD "move "
#define RMCMD "del "
#else
#define MOVECMD "mv "
#define RMCMD "rm "
#endif

void version(int argc, char **argv);
int dilca_configuration_load(char *configuration_path);
int dilca_dir_polling(char *dir);
int dilca_read_file_all(char *filename);
bool idmef_move(char *destination, char *source);
bool CUSTOM_INRECEIVE_FUNCTION_I(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame, axlPointer data);


char dilca_dir_tmp[255];
char dilca_dir_store[255];
char dilca_dir_react[255];
int dilca_polling;
int dilca_retry;
int dilca_reallocation_size;


int main(int argc, char **argv){
	IdxpConnection *connection=NULL;
	IdxpChannel *channel=NULL;

	version(argc,argv);
	IDXPLIB_LISTENER

        (argc==5) ? idxp_configuration_load(argv[1],NULL) : (printf("\nUsage: %s <idxp-conf> <dilca-conf> <listen-add> <listen-port>\n",argv[0]) , exit(-1));
	(argc==5) ? dilca_configuration_load(argv[2]) : (printf("\nUsage: %s <idxp-conf> <dilca-conf> <listen-add> <listen-port>\n",argv[0]) , exit(-1));

	idxp_custom_alert_server_set(CUSTOM_INRECEIVE_FUNCTION_I);
	connection = idxp_connection_new(connection,argv[3],argv[4]);
	dilca_dir_polling(dilca_dir_react);
	idxp_listener_wait();
	idxp_exit();

	return 1;
}

#ifdef _WIN32
static void version(int argc, char **argv){
#else
void version(int argc, char **argv){
#endif
	if(argc <= 1) return;
	if(strcmp(argv[1],"-v")==0){ printf(_VERSION1); printf("\n"); exit(0); }
	if(strcmp(argv[1],"-V")==0){ printf(_VERSION); printf("\n"); exit(0); }
	return;
}



int dilca_configuration_load(char *configuration_path){
        FILE *conf_file;
        char parm_name[100],parm_val[100];

        /* Parameters initialization */
        dilca_dir_tmp[0] = '\0';
        dilca_dir_store[0] = '\0';
        dilca_dir_react[0] = '\0';
        dilca_polling = 1000;
        dilca_retry = 10;
        dilca_reallocation_size = 1000;

        if((conf_file=fopen(configuration_path,"rt"))==NULL){
                fprintf(stderr,"ERR - Cannot open %s conf file!\n",configuration_path);
                return false;
        }

        while(!feof(conf_file)){
                fscanf(conf_file,"%s = %99[^\n]",parm_name,parm_val);
                /* dilca_dir_tmp = ... */
                if(strncasecmp(parm_name,"dilca_dir_react",15)==0)  strcpy(dilca_dir_react,parm_val);
                /* dilca_dir_tmp = ... */
                if(strncasecmp(parm_name,"dilca_dir_tmp",13)==0)  strcpy(dilca_dir_tmp,parm_val);
                /* dilca_dir_store = ... */
                if(strncasecmp(parm_name,"dilca_dir_store",15)==0)  strcpy(dilca_dir_store,parm_val);
                /* dilca_retry = ... */
                if(strncasecmp(parm_name,"dilca_retry",11)==0)  sscanf(parm_val,"%d",&dilca_retry);
                /* dilca_reallocation_size = ... */
                if(strncasecmp(parm_name,"dilca_reallocation_size",23)==0) sscanf(parm_val,"%d",&dilca_reallocation_size);
                /* dilca_polling = ... */
                if(strncasecmp(parm_name,"dilca_polling",13)==0) sscanf(parm_val,"%d",&dilca_polling);
        }

        fclose(conf_file);

        #ifndef _WIN32
        dilca_polling *= 1000;
        #endif
        if((strlen(dilca_dir_react)<2) ||(strlen(dilca_dir_tmp)<2) || (strlen(dilca_dir_store)<2)){ fprintf(stderr,"ERR - Directories Parameters undefined, exiting ..\n"); exit(-1);}
        return true;
}



bool CUSTOM_INRECEIVE_FUNCTION_I(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame, axlPointer data){
	char filename_tmp[256];
	char filename_store[256];
	struct timeval tspc;

	#ifdef _WIN32
	win_gettimeofday(&tspc,NULL);
	#else
	gettimeofday(&tspc,NULL);
	#endif

	snprintf(filename_tmp,strlen(dilca_dir_tmp)+27,"%s%010ld%010ld.idmef",dilca_dir_tmp,tspc.tv_sec,tspc.tv_usec);
	snprintf(filename_store,strlen(dilca_dir_store)+27,"%s%010ld%010ld.idmef",dilca_dir_store,tspc.tv_sec,tspc.tv_usec);
	lightlog_idmef_write(filename_tmp,ll_INFORMATIONAL,0,(char*)idxp_frame_get_payload(frame));
	idmef_move(filename_store,filename_tmp);
        return true;
}

bool idmef_move(char *destination, char *source){
	char command[256];

	sprintf(command,"%s \"%s\" \"%s\"",MOVECMD,source,destination);
	system(command);

	return true;
}

int dilca_dir_polling(char *dir){
        struct direct **namelist;
        char rmcmd[255];
        char filename[255];
        int i,n;

        /******************************************************************/
        /** Scanning directory                                           **/
        /******************************************************************/
        while(1){
		n = scandir(dir, &namelist, 0, alphasort);
        	if(n<0){
               		fprintf(stderr,"ERR - Unable to scan %s\n",dir);
                	return -1;
        	}
	
                for(i=0;i<n;i++){
                        if(!((namelist[i]->d_name[0]=='.')&&((namelist[i]->d_name[1]=='.')||(namelist[i]->d_name[1]=='\0')))){
                                sprintf(filename,"%s%s",dir,namelist[i]->d_name);
                                dilca_read_file_all(filename);
                                #ifdef _WIN32
                                snprintf(rmcmd,strlen(dir)+strlen(namelist[i]->d_name)+strlen(RMCMD)+3,"%s\"%s%s\"",RMCMD,dir,namelist[i]->d_name);
                                #else
                                snprintf(rmcmd,strlen(dir)+strlen(namelist[i]->d_name)+strlen(RMCMD)+3,"%s\"%s%s\"",RMCMD,dir,namelist[i]->d_name);
                                #endif
                                system(rmcmd);
                        }
                        free(namelist[i]);
                }
                free(namelist);
                usleep(dilca_polling);
        }
}



int dilca_read_file_all(char *filename){
        FILE *fp1;
        char *buff,c='a';
        int size=0,bufflen=0,realloc_cnt=0,retry=0;

        for(retry=0,fp1=fopen(filename,"rt");((fp1==NULL) && (retry<=dilca_retry));retry++,usleep(200),fp1=fopen(filename,"rt"));
        if(fp1==NULL){
                fprintf(stderr,"ERR - Cannot open %s file\n",filename);
                return -1;
        }
        size=0;realloc_cnt=0,c='a';
        buff=NULL;
        buff=(char *)calloc(sizeof(char),dilca_reallocation_size);
        realloc_cnt+=dilca_reallocation_size;
        buff[size]=fgetc(fp1);
        while(!feof(fp1)){
        	if(size == realloc_cnt){
                	buff=(char*)realloc(buff,sizeof(char)*(size + dilca_reallocation_size));
                        realloc_cnt+=dilca_reallocation_size;
                }
                size++;
                buff[size]=fgetc(fp1);
        }
        buff[size]='\0';
        if(size>1) idxp_broadcast_send_message(IDXPROLE_EC,buff);
        free(buff);
        buff=NULL;
        fclose(fp1);
        return 1;
}

